using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace OrtzEng.Physics
{
    public class BoundingBox2D
    {
        protected Vector2 min, max;
        protected float width, height;

        public Vector2 Min { get { return min; } }
        public Vector2 Max { get { return max; } }
        public float Width { get { return width; } }
        public float Height { get { return height; } }

        public BoundingBox2D(Vector2 position, float width, float height)
        {
            this.width = width;
            this.height = height;

            Move(position);
        }

        public BoundingBox2D(float width, float height)
            : this(Vector2.Zero, width, height)
        {
        }

        public void Move(Vector2 position)
        {
            min.X = position.X;
            min.Y = position.Y;

            max.X = position.X + width;
            max.Y = position.Y + height;
        }

        public void Bump(Vector2 adjustment)
        {
            min += adjustment;
            max += adjustment;
        }

        /// <summary>
        /// Calculates the minimum translation distance (MTD) needed to seperate two bounding boxes.
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns>The minimum translation distance (MTD) needed to seperate the two boxes.  Vector2.Zero if no intersection exists.</returns>
        public static Vector2 CalculateMinimumTranslationDistance(BoundingBox2D left, BoundingBox2D right)
        {
            // Our displacement result vector containing the translation (movement) information
            // that resolves our intersection.
            Vector2 result = Vector2.Zero;

            // This is re-used to calculate the difference in distance between sides.
            float difference = 0.0f;

            // This stores the absolute minimum distance we'll need to separate our colliding object.
            float minimumTranslationDistance = 0.0f;

            // Axis stores the value of X or Y.  X = 0, Y = 1.
            // Side stores the value of left (-1) or right (+1).
            // They're used later in calculating the result vector.
            int axis = 0, side = 0;

            // Left
            difference = left.Max.X - right.Min.X;
            if (difference < 0.0f)
            {
                return Vector2.Zero;
            }
            {
                // These braces are superfluous but should make it more clear that they're similar
                // to the if statements below.
                minimumTranslationDistance = difference;
                axis = 0;
                side = -1;
            }

            // Right
            difference = right.Max.X - left.Min.X;
            if (difference < 0.0f)
            {
                return Vector2.Zero;
            }
            if (difference < minimumTranslationDistance)
            {
                minimumTranslationDistance = difference;
                axis = 0;
                side = 1;
            }

            // Down
            difference = left.Max.Y - right.Min.Y;
            if (difference < 0.0f)
            {
                return Vector2.Zero;
            }
            if (difference < minimumTranslationDistance)
            {
                minimumTranslationDistance = difference;
                axis = 1;
                side = -1;
            }

            // Up
            difference = right.Max.Y - left.Min.Y;
            if (difference < 0.0f)
            {
                return Vector2.Zero;
            }
            if (difference < minimumTranslationDistance)
            {
                minimumTranslationDistance = difference;
                axis = 1;
                side = 1;
            }

            // Intersection occurred:
            if (axis == 1) // Y Axis
                result.Y = (float)side * minimumTranslationDistance;
            else // X Axis
                result.X = (float)side * minimumTranslationDistance;

            return result;
        }
    }
}
